import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { DeleteResult, In, Repository } from 'typeorm';
import { Questions } from './questions.entity';
import { Answer } from '../answer/answer.entity';
import { CheckEnum } from '../answer/answer.enum';
import { RewardSuccess } from '../rewardSuccess/rewardSuccess.entity';
import { payStatusEnum } from '../reward/reward.enum';
import { Reward } from '../reward/reward.entity';
import Database from 'src/config/database';
import { WXAPI } from 'src/common/wx_api';
import utils from 'src/common/utils';
import { Video } from '../video/video.entity';
import { system_wx_user, temp_wx_user, video_SubAppId, wx_secret_yz_zuozhedua } from 'src/setting';
import { Profit } from '../profit/profit.entity';
import { profitEnum, profitTypeEnum } from '../profit/profit.enum';
import { Notices } from '../notices/notices.entity';
import { NoticeIsDeleteEnum } from '../notices/notices.enum';
import { QuestionDeleteTag } from './questions.enum';
import { RedisCacheService } from '../redisCache/redisCache.service';
import { WxUser } from '../wxUser/wxUser.entity';
let WXAPIOBJ = new WXAPI()

@Injectable()
export class QuestionsService {
  constructor(
    @InjectRepository(Questions)
    private repository: Repository<Questions>,
    @InjectRepository(Answer)
    private answerRepository: Repository<Answer>,
    @InjectRepository(RewardSuccess)
    private rewardSuccessRepository: Repository<RewardSuccess>,
    @InjectRepository(Reward)
    private rewardRepository: Repository<Reward>,
    @InjectRepository(Video)
    private videoRepository: Repository<Video>,
    @InjectRepository(Profit)
    private profitRepository: Repository<Profit>,
    @InjectRepository(Notices)
    private noticesRepository: Repository<Notices>,
    private readonly redisCacheService: RedisCacheService,
    @InjectRepository(WxUser)
    private wxUserRepository: Repository<WxUser>,
  ) {}

  findAll(): Promise<Questions[]> {
    return this.repository.find();
  }

  findOne(id: any): Promise<Questions> {
    return this.repository.findOne(id);
  }

  async remove(video_id: number, wx_user: string, not_delete_video_source?: boolean): Promise<Boolean> {
    //查询用户是否有悬赏，并且没有发答案
    // let findReward = await this.rewardSuccessRepository.findOne({where:{ video_id: video_id, wx_user: wx_user}})
    let findRewards = await this.rewardSuccessRepository.query(`
      select * from reward_success 
      where reward_success.video_id not in (
        select answer.video_id from profit
        inner join answer on answer.id = profit.answer_id
        where answer.check = 1 and answer.video_id = ? and profit.use_wx_user = ?
      ) and reward_success.video_id = ? and reward_success.wx_user = ?
    `,[video_id, wx_user, video_id, wx_user])
    //判断作品是否有答案
    //有答案了就不能返回悬赏
    //没答案会退回悬赏
    let findAnswer = await this.answerRepository.findOne({where:{video_id: video_id, check: CheckEnum.yes}})
    // if(findAnswer){
    //   findReward = undefined
    // }
    let findVideo = await this.videoRepository.findOne({where:{ id: video_id }})
    let findQuestion = await this.repository.findOne({where:{video_id: video_id, wx_user: wx_user}})
    //查询是否有申请退款
    let findRefund = findAnswer ? await this.profitRepository.findOne({where:{answer_id: findAnswer.id, status: profitEnum.refoundIng, use_wx_user: wx_user}}) : undefined
    
    let db: Database = new Database()
    let connection = await db.getConnection()
    const queryRunner = connection.createQueryRunner()
    await queryRunner.connect()
    // 开始事务
    await queryRunner.startTransaction()
    try {
      //判断是否已发货
      if(findQuestion){
        if(findQuestion.post_answer == 1){
          //修改删除状态
          await this.repository.createQueryBuilder(null, queryRunner)
            .update({delete_tag: QuestionDeleteTag.yes})
            .where({id: findQuestion.id})
            .execute()
        }else{
          await this.repository.createQueryBuilder(null ,queryRunner).delete().where({video_id: video_id, wx_user: wx_user}).execute()
        }
      }else{
        //没悬赏直接删除    
        await this.repository.createQueryBuilder(null ,queryRunner).delete().where({video_id: video_id, wx_user: wx_user}).execute()
      }
      //如果视频作者是当前用户，并且视频没有审核通过，直接删除视频
      //视频的作者是系统用户，直接删除视频
      console.log(findVideo, not_delete_video_source, 'not_delete_video_source')
      if(!not_delete_video_source && ((findVideo?.wx_user === wx_user && findVideo?.check === CheckEnum.no) || (wx_user === system_wx_user && findVideo.wx_user === system_wx_user))){
        await this.videoRepository.createQueryBuilder(null, queryRunner).delete().where({id: video_id}).execute()

        findRewards = await this.rewardSuccessRepository.query(`
          select * from reward_success 
          where reward_success.video_id = ?
        `,[video_id])

        //删除所有提问
        await this.repository.createQueryBuilder(null ,queryRunner).delete().where({video_id: video_id}).execute()

      }
      //设置通知为已经删除的状态
      await this.noticesRepository.createQueryBuilder(null, queryRunner).update({is_delete: NoticeIsDeleteEnum.yes}).where({video_id: video_id, wx_user: wx_user}).execute()

      //有悬赏，退回悬赏
      if(findRewards.length > 0){
        let deleteReward = () => {
          return new Promise((resolve, reject) => {
            let len = findRewards.length
            findRewards.map(async findReward => {
              //退款
              //修改状态为已退款
              await this.rewardRepository.createQueryBuilder(null,queryRunner).update({pay_status:payStatusEnum.reject}).where({pay_order: findReward.pay_order}).execute()
              await this.rewardSuccessRepository.createQueryBuilder(null,queryRunner).delete().where({id:findReward.id}).execute()
              //删除收益表
              if(findAnswer){
                await this.profitRepository.createQueryBuilder(null, queryRunner).delete().where({answer_id: findAnswer.id, use_wx_user: wx_user, status: profitEnum.entry}).execute()
              }
              await WXAPIOBJ.clearPayWallet(findReward.wx_user)
              if(--len == 0){
                resolve(true)
              }
            })
          })
        }
        await deleteReward()
      }

      //取消退款申请
      if(findRefund){
        await this.profitRepository.createQueryBuilder(null, queryRunner).update({status: profitEnum.entry}).where({id: findRefund.id}).execute()
      }
        
      await queryRunner.commitTransaction()
      await queryRunner.release();

      //清空同提问缓存
      await this.redisCacheService.del(`videos:${video_id}:question:${wx_user}`)
      await this.redisCacheService.del(`videos:${video_id}:questioncount`)
      if(findRefund){
        await this.redisCacheService.clear(`${wx_user}:consume_list:consume*`)
      }
      return true
    } catch (err) {
      // 有错误做出回滚更改
      await queryRunner.rollbackTransaction()
      await queryRunner.release();
      return false
    }
  

  }


  /**
   * 查询所有充值成功的钱总数
   * @param wx_user 用户标识
   * @returns 
   */
  async sumRechargeAmount(wx_user: string){
    let result = await this.repository.query(`
      select case when a.amount is null then 0 else a.amount end as amount
      from (
        select sum(amount) as amount
        from recharge_flow
        where wx_user = ?
          and status = 1
      ) a
    `,[wx_user])
    if(result.length > 0){
      return result[0].amount
    }else{
      return 0
    }
  }

  /**
   * 查询所有消费的钱总数
   * @param wx_user 用户标识
   * @returns 
   */
  async profitAmount(wx_user: string){
    let result = await this.repository.query(`
      select case when a.unit_price is null then 0 else a.unit_price end as unit_price
      from (
        select sum(unit_price) unit_price from (
          select sum(unit_price) + sum(service_charge) as unit_price
          from profit
          where use_wx_user = ?
            and type = 1
            and unit_price > 0
            and (status = 1 or status = 3)
          union all
          select sum(unit_price) + sum(service_charge) as unit_price
          from profit_unlock_home
          where use_wx_user = ?
            and type = 1
            and unit_price > 0
            and (status = 1 or status = 3)
        )a
      ) a
    `, [wx_user, wx_user])
    if(result.length > 0){
      return result[0].unit_price
    }else{
      return 0
    }
  }

  /**
   * 查询所有悬赏的钱总数
   * @param wx_user 用户标识
   */
  async selectTotalRewardSuccessByWxUser(wx_user: string){
    let result = await this.repository.query(`
      select case when a.amount is null then 0 else a.amount end amount
      from (
        select sum(unit_price) as amount
        from reward
        where wx_user = ?
          and pay_status = 1 and video_id not in (
          select answer.video_id from profit
            inner join answer on answer.id = profit.answer_id
          where profit.use_wx_user = ?
        )
      ) a
    `, [wx_user, wx_user])
    if(result.length > 0){
      return result[0].amount
    }else{
      return 0
    }
  }

  async create(questions: Questions, uid: number, share_uid: number): Promise<{success: boolean, type?: string, error?: string}> {
    let findQuestion = await this.repository.findOne({where:{video_id: questions.video_id, wx_user: questions.wx_user}})
    //查询是否是大额悬赏
    let findUnitPriceBig: RewardSuccess[] = await this.rewardSuccessRepository.query(`
      select reward_success.* from reward_success
      inner join video on reward_success.video_id = video.id
      where video.id = ? and reward_success.unit_price = 20000
      limit 0,1
    `,[questions.video_id])
    //大额提问先检查账户是否足够扣费
    if(findUnitPriceBig.length > 0){
      //查询钱包余额
      //先查询redis
      let wallet = await WXAPIOBJ.getWallet(questions.wx_user)
      console.log(wallet)
      if(!wallet){
        //查询所有充值成功的钱总数
        let sumRechargeAmount = await this.sumRechargeAmount(questions.wx_user);
        //查询所有消费的钱总数
        let profitAmount = await this.profitAmount(questions.wx_user);
        //查询所有悬赏的钱总数
        let rewardAmount = await this.selectTotalRewardSuccessByWxUser(questions.wx_user);
        console.log(sumRechargeAmount)
        console.log(profitAmount)
        console.log(rewardAmount)
        //计算剩余钱数
        // 充值 - 消费 - 悬赏 + 广告 - 已提现 = 余额
        wallet = sumRechargeAmount - profitAmount - rewardAmount;
      }
      wallet = wallet || 0
      if(Number(wallet) < Number(findUnitPriceBig[0].unit_price)){
        return {success:true, type: 'balance_not_enough'}
      }
    }
    if(!share_uid || share_uid == -1){
      let findShareUid = await this.repository.query(`select id from wx_user where wx_user.openid = ?`,[questions.wx_user])
      if(findShareUid.length > 0){
        share_uid = findShareUid[0].id
      }
    }
    questions.group_uid = share_uid
    let db: Database = new Database()
    let connection = await db.getConnection()
    const queryRunner = connection.createQueryRunner()
    await queryRunner.connect()
    // 开始事务
    await queryRunner.startTransaction()
    try {
      let type = ''
      if(findQuestion){
        if(findQuestion.post_answer == 1){
          //修改删除状态
          await this.repository.createQueryBuilder(null, queryRunner)
            .update({delete_tag: QuestionDeleteTag.yes})
            .where({id: findQuestion.id})
            .execute()
        }else{
          await this.repository.createQueryBuilder(null, queryRunner)
            .delete()
            .where({id: findQuestion.id})
            .execute()
        }
        //设置通知为已经删除的状态
        await this.noticesRepository.createQueryBuilder(null, queryRunner)
          .update({is_delete: NoticeIsDeleteEnum.yes})
          .where({video_id: questions.video_id, wx_user: questions.wx_user})
          .execute()
        type = 'delete'
      }else{
        //查询作品是否有答案
        let findAnswer = await this.answerRepository.findOne({ where: {video_id: questions.video_id, check: CheckEnum.yes}})
        let isAnswer = findAnswer ? true : false
        if(!findAnswer){
          //查询视频详情
          let findVideo = await this.videoRepository.findOne({where:{id: questions.video_id}})
          if(findVideo?.ic_group){
            isAnswer = true
          }
        }
        if(isAnswer){
          let nowTime = new Date()
          let min = nowTime.getTime()
          nowTime.setMinutes(nowTime.getMinutes() + 1)
          let max = nowTime.getTime()
          let rand = Math.random()
          let range = max - min
          let answerTime = min + Math.floor(rand * range)
          answerTime = nowTime.getTime()
          nowTime.setTime(answerTime)
          questions.answer_time = nowTime

          //a分享给b，查询a用户的提问发货时间
          if(share_uid && share_uid > 0){
            let findAQuestion = await this.repository.query(`
              select questions.* from questions
              where questions.group_uid = ? and questions.video_id = ?
            `,[share_uid, questions.video_id])
            if(findAQuestion.length > 0){
              findAQuestion = findAQuestion[0]
              questions.answer_time = findAQuestion.answer_time
              questions.rela_questions_wx_user = findAQuestion.wx_user
            }else{
              let findWxUser = await this.repository.query(`
                select * from wx_user where id = ?
              `,[share_uid])
              if(findWxUser.length > 0){
                questions.rela_questions_wx_user = findWxUser[0].openid
              }
            }
          }else{
            //查询我是否分享给其他人，并且其他人有过同提问，其他人同提问的时间
            let findOtherTime = await this.repository.query(`
              select * from questions
              where questions.video_id = ? and questions.rela_questions_wx_user = ?
              limit 0,1
            `,[questions.video_id, questions.wx_user])
            if(findOtherTime.length > 0){
              questions.answer_time = findOtherTime[0].answer_time
            }
          }
        }
        //大额悬赏，添加悬赏
        if(findUnitPriceBig.length > 0){
          let unitPriceBig = findUnitPriceBig[0]
          //悬赏流水表
          let reward = new Reward()
          reward.video_id = questions.video_id
          reward.create_time = new Date()
          reward.wx_user = questions.wx_user
          reward.unit_price = unitPriceBig.unit_price
          reward.service_charge = unitPriceBig.service_charge
          reward.pay_status = payStatusEnum.success
          reward.pay_order = "rewardquestionbig" + utils.Format(new Date(),"yyyyMMddhhmmss") + new Date().getTime();
          reward.pay_time = reward.create_time
          await this.rewardRepository.createQueryBuilder(null, queryRunner)
            .insert()
            .into(Reward)
            .values(reward)
            .execute()

          //成功悬赏表
          let rewardSuccess = new RewardSuccess()
          rewardSuccess.pay_order = reward.pay_order
          rewardSuccess.pay_time = new Date()
          rewardSuccess.service_charge = unitPriceBig.service_charge
          rewardSuccess.unit_price = unitPriceBig.unit_price
          rewardSuccess.video_id = questions.video_id
          rewardSuccess.wx_user = questions.wx_user
          await this.rewardSuccessRepository.createQueryBuilder(null, queryRunner)
            .insert()
            .into(RewardSuccess)
            .values(rewardSuccess)
            .execute()
          await WXAPIOBJ.clearPayWallet(questions.wx_user)
        }

        await this.repository.createQueryBuilder(null, queryRunner)
          .insert()
          .into(Questions)
          .values(questions)
          .execute()
        type = 'add'
      }


      await queryRunner.commitTransaction()
      await queryRunner.release();

      //清空同提问缓存
      await this.redisCacheService.del(`videos:${questions.video_id}:question:${questions.wx_user}`)
      await this.redisCacheService.del(`videos:${questions.video_id}:questioncount`)

      return {success:true, type: type}
    } catch (err) {
      // 有错误做出回滚更改
      await queryRunner.rollbackTransaction()
      await queryRunner.release();
      return {success:false, error: err?.toString()}
    }
  }

  /**
   * 是否可以写答案
   */
  async isCreate(video_id: number, wx_user: string, group_id: any){
    //视频是否存在
    let findVideo = await this.videoRepository.findOne({where:{id: video_id, check: 1, delete_tag: 0}})
    if(!findVideo){
      return {error: '视频不存在'}
    }
    else{
      if(!group_id || isNaN(parseInt(group_id)) || group_id < 0){
        let findUser = await this.wxUserRepository.findOne({where:{openid: wx_user}})
        group_id = findUser.id
      }
      //如果视频有答案了如果别人收到答案了
      let findIsQuestions = await this.repository.query(`
        select id from questions
        where post_answer = 1 and questions.group_uid = ? and questions.video_id = ?
      `,[group_id, video_id])
      if(findIsQuestions.length > 0){
        return {error: '问题已解决'}
      }else if(findVideo.ic_group){
        let findIc = await this.videoRepository.query(`
          select video.id from video
          inner join internet_celebrity_group on internet_celebrity_group.id = video.ic_group
          inner join platform on platform.ic_group = video.ic_group
          where video.id = ? and (
            (
              video.overseas = 1 and video.profit_type = 0 and video.original = 1
            )
            or (
              video.overseas = 3 and video.profit_type = 0 and video.original = 1
            )
            or(
              (video.overseas = 0 or video.original = 0) 
              and (
                (
                  internet_celebrity_group.type = 0 and 
                  (
                    platform.platform in (select setting.value from setting where setting.key = 'level3')
                    or (select count(1) from platform where platform.platform != '' and platform.ic_group = internet_celebrity_group.id) = 0
                  )
                )
                or internet_celebrity_group.type = 3
              )
              and (
                (video.original = 0 and (video.in_ic = 0 or video.in_ic is null))
                or (video.original = 1 and video.in_ic = 0)
              )
            )
          )
        `,[video_id])
        if(findIc.length > 0){
          return {error: '问题已解决'}
        }else{
          //查询分享连上的人回答被采纳
          let findShareCheckAnswer = await this.answerRepository.findOne({where:{video_id: video_id, group_uid: group_id, check: In([0,1])}})
          if(findShareCheckAnswer){
            return {error: '问题已解决'}
          }
        }
      }
    }
    return {}
  }
}